
#include <base/directorymanager.h>
#define ZLIB_WINAPI
#include <unzip.h>
#include <fstream>
#include <windows.h>
#include <event/events.h> //only used for debugging?

#pragma comment (lib, "zlibwapi.lib")

typedef stdext::hash_map<std::string, DirectoryLocator> zip_map;

DirectoryManager::DirectoryManager(){
}

void DirectoryManager::indexDirectory(const std::string & path){
	WIN32_FIND_DATA result;
	HANDLE h;

  std::string searchpath = path;
  searchpath += "\\*";
  
	h = FindFirstFile(searchpath.c_str(), &result);

	if(h != INVALID_HANDLE_VALUE){
		do{
			std::string name = result.cFileName;
      //events::Fire(new events::PrintConsole(name + " <- found"));
			if(result.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
        if(name != "." && name != ".."){
				indexDirectory(path + "\\" + name);
        }
			}else if(!name.compare(name.length() - 4, 4, ".zip")){
				unzFile zipfile;
				char zipfilepath[128];
				zipfile = unzOpen(name.c_str());
				for(unzGoToFirstFile(zipfile);unzGoToNextFile(zipfile) == UNZ_OK;){
					unzGetCurrentFileInfo(zipfile, NULL,zipfilepath,128,NULL,0,NULL,0);
					std::string keypath = path + "\\" + zipfilepath;
					addIndex(keypath, path + "\\" + name, zipfilepath);
				}
				unzClose(zipfile);
			}else{
        addIndex(path + "\\" + name, path + "\\" + name, "");
			}
		}while(FindNextFile(h, &result));
		FindClose(h);
  }
}

void DirectoryManager::addIndex(const std::string & key, const std::string & path, const std::string & zippath){
	char fullkey[512];
  char fullpath[512];

  GetFullPathName(key.c_str(), 512, fullkey, NULL);
  GetFullPathName(path.c_str(), 512, fullpath, NULL);

	for(int i = 0; fullkey[i]; i++){
    fullkey[i] = tolower(fullkey[i]);
		if(fullkey[i] == '/') fullkey[i] = '\\';
  }

  for(int i = 0; fullpath[i]; i++){
    fullpath[i] = tolower(fullpath[i]);
		if(fullpath[i] == '/') fullpath[i] = '\\';
  }

  //events::Fire(new events::PrintConsole(std::string(fullkey) + " <- indexed"));
  _directory_map.insert(zip_map::value_type(fullkey, DirectoryLocator(fullpath, zippath)));
}

int DirectoryManager::load(const std::string & path, char ** data){
  int size = -1;
  char temp[512];

  GetFullPathName(path.c_str(), 512, temp, NULL);

  for(int i = 0; temp[i]; i++){
    temp[i] = tolower(temp[i]);
		if(temp[i] == '/') temp[i] = '\\';
  }

  zip_map::iterator i = _directory_map.find(temp);
  events::Fire(new events::PrintConsole(temp));
  if(i == _directory_map.end()){
    return -1;
  }
  if(i->second.zippath.length() == 0){
    std::ifstream file;
		std::filebuf *pbuf; 
    file.clear();
    //events::Fire(new events::PrintConsole(i->second.path + " what?"));
    file.open(i->second.path.c_str(), std::ios::binary);
      //file.open("stages/test.lua", std::ios::binary);
    if(file.fail()){ 
      //events::Fire(new events::PrintConsole("sorry charlie"));
      return -1;
    }
		pbuf = file.rdbuf();
    size = pbuf->pubseekoff(0,std::ios::end,std::ios::in);
    pbuf->pubseekpos(0,std::ios::in);
    *data = new char[size];
    pbuf->sgetn(*data, size);
    file.close();
  }else{
    unzFile zipfile;
    unz_file_info info;
    zipfile = unzOpen(i->second.path.c_str());
    if(unzLocateFile(zipfile, i->second.zippath.c_str(), 0) != UNZ_OK)
      return -1;
    unzGetCurrentFileInfo(zipfile,&info,NULL,0,NULL,0,NULL,0);
    size = info.uncompressed_size;
    unzOpenCurrentFile(zipfile);
    *data = new char[size];
    unzReadCurrentFile(zipfile, *data, size);
    unzClose(zipfile);
  }

  return size;
}
